package dnl.jexem.cmd;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 *
 * @author Daniel Orr
 */
public final class ControlThread extends Thread {

    private final List<ExecutionInfo> localExecutions = new ArrayList<>();

    private static ControlThread controlThreadInstance;

    private boolean stop;
    private static Object lock = new Object();

    private ControlThread() {
        setDaemon(true);
    }

    public static void register(BaseLocalCommandExecution commandExecution, long timeout) {
        synchronized (lock) {
            if (controlThreadInstance == null || controlThreadInstance.stop) {
                controlThreadInstance = new ControlThread();
            }
            controlThreadInstance.registerImpl(commandExecution, timeout);
            if (!controlThreadInstance.isAlive()) {
                controlThreadInstance.start();
            }
        }
    }

    private void registerImpl(BaseLocalCommandExecution commandExecution, long timeout) {
        ExecutionInfo executionInfo = new ExecutionInfo(commandExecution, timeout);
        localExecutions.add(executionInfo);
    }

    @Override
    public void run() {
        synchronized (lock) {
            while (!stop) {
                try {
                    if (localExecutions.isEmpty()) {
                        stop = true;
                        return;
                    }
                    for (Iterator<ExecutionInfo> it = localExecutions.iterator(); it.hasNext();) {
                        ExecutionInfo executionInfo = it.next();
                        final BaseLocalCommandExecution commandExecution = executionInfo.commandExecution;
                        if (commandExecution.hasTerminated()) { // cleanup
                            it.remove();
                        }
                        if (System.currentTimeMillis() - commandExecution.getStartTime() > executionInfo.timeout) {
                            commandExecution.killOnTimeout();
                        }
                    }

                    try {
                        Thread.sleep(DEFAULT_SLEEP_TIME);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } catch (Exception e) {
                    System.out.println("");
                }
            }
        }
    }
    public static final int DEFAULT_SLEEP_TIME = 5000;

    private static class ExecutionInfo {

        BaseLocalCommandExecution commandExecution;
        long timeout;

        public ExecutionInfo(BaseLocalCommandExecution commandExecution, long timeout) {
            this.commandExecution = commandExecution;
            this.timeout = timeout;
        }

    }
}
